package edu.bu.cs673.superkids123.children.controller.lessons;

import java.lang.reflect.InvocationTargetException;

import javax.swing.ImageIcon;
import javax.swing.SwingUtilities;

import edu.bu.cs673.superkids123.AbstractFrame;
import edu.bu.cs673.superkids123.children.DataObjectAccess.LessonGameManager;
import edu.bu.cs673.superkids123.children.controller.AbstractLessonController;
import edu.bu.cs673.superkids123.children.model.Lesson;
import edu.bu.cs673.superkids123.children.model.resources.AudioPlayer;
import edu.bu.cs673.superkids123.children.model.resources.ChildrenResource;
import edu.bu.cs673.superkids123.children.model.resources.ChildrenResourceProvider;
import edu.bu.cs673.superkids123.children.view.ActivitiesMenuView;
import edu.bu.cs673.superkids123.children.view.lessons.CountingLessonView;
import edu.bu.cs673.superkids123.children.view.lessons.LessonResultsView;


/**
 * Class CountingLessonController
 * 
 * This is the controller class that supports the counting lesson.
 * The back, play, and forward buttons from the CountingLessonView class
 * are handled here. additionally, the numbers image buttons can be pressed to 
 * hear the audio for the individual number.
 * 
 * @author David Bardwell
 * 
 */
public class CountingLessonController extends AbstractLessonController {

    private final int minStartingNumber = 1;
    private final int maxStartingNumber = 10;
    private final int standardIncrementValue = 3;
    private final int numberOfScreenGroups = 4;
    private int currentStartingNumber = 1;
    private boolean stopPlay = false;
        
    private ChildrenResourceProvider provider = ChildrenResourceProvider.getInstance();
        
    public CountingLessonController(AbstractFrame mainFrame) {
        super(mainFrame);
    }
        
    public int getCurrentStartingNumber() {
        return currentStartingNumber;
    }
        
    public void setStopPlay(boolean stopState) {
        stopPlay = stopState;
    }
        
    public boolean getStopPlay() {
            return stopPlay;
    }
        
    public void navigateBackButtonPressed() {
        getMainFrame().changeView(ActivitiesMenuView.class);
    }
        
    public void avatarButtonPressed() {
        getMainFrame().changeView(LessonResultsView.class);
        /*avatarButton goes to lessonResultsView for demonstration purposes,
          this is temporary and should be updated*/
    }
        
    /**
     * playAllButtonPressed
     * Walk thru all the numbers from 1 to 12 currently and play the
     * audio for each number. 
     * 
     * @param CountingLessonView view
     * 
     */
    public void playAllButtonPressed(CountingLessonView view) {
        final CountingLessonView view2 = view;
        view2.setBusy(true);
        
        Thread myPlayAllThread = new Thread() {
            public void run() {
                CountingLessonController.this.setStopPlay(false);
                currentStartingNumber = minStartingNumber;
                view2.setAudioActive(true);
                for (int screenGroup = 0; screenGroup < numberOfScreenGroups; screenGroup++) {
                    try {
                        SwingUtilities.invokeAndWait(new Runnable() {
                            public void run() {
                                view2.initializeCountingButtons();
                                view2.showCountingButtons();
                            }
                        });
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                    int j = 0;
                    for (int i = currentStartingNumber; 
                        i < currentStartingNumber + standardIncrementValue; i++) {
                         view2.setCurrentAudioNumber(j);
                         forceRepaintInThread(view2);
                                
                         // Check if user stopped play, if so, abort
                         if (CountingLessonController.this.getStopPlay() == true) {
                             view2.setAudioActive(false);
                             forceRepaintInThread(view2);
                             view2.setBusy(false);
                             return;
                         }
                        
                         playAudioForNumber(i, view2);
                         view2.setBusy(true);
                        j++;
                    }
                    currentStartingNumber += standardIncrementValue;
                }
                view2.setAudioActive(false);
                forceRepaintInThread(view2);
                currentStartingNumber = maxStartingNumber;
                view2.setBusy(false);
            }
        };
        myPlayAllThread.start();
    }
        
    /**
     * playButtonPressed
     * 
     * Audio is played for the current 3 number group. Additionally, each
     * number graphic group below the number image is highlighted as red when
     * the number is made audible through the audio player.
     * 
     * Separate threads are needed to make this work correctly. The
     * event dispatch thread on which the play button action starts, must
     * terminate so the paint activity on the panel can work correctly. 
     * 
     * @param CountingLessonView view
     */
    public void playButtonPressed(CountingLessonView view) {
        final CountingLessonView view2 = view;
        view2.setBusy(true);
                
        Thread myPlayThread = new Thread() {
            public void run() {
                CountingLessonController.this.setStopPlay(false);
                view2.setAudioActive(true);
                int j = 0;
                for (int i = currentStartingNumber; 
                    i < currentStartingNumber + standardIncrementValue; i++) {
                     view2.setCurrentAudioNumber(j);
                     forceRepaintInThread(view2);
                                
                     // Check if user stopped play, if so, abort
                     if (CountingLessonController.this.getStopPlay() == true) {
                         view2.setAudioActive(false);
                         forceRepaintInThread(view2);
                         view2.setBusy(false);
                         return;
                     }
                        
                     playAudioForNumber(i, view2);
                     view2.setBusy(true);
                     j++;
                 }
                 view2.setAudioActive(false);
                 forceRepaintInThread(view2);
                 view2.setBusy(false);
            }
        };
        myPlayThread.start();
    }
        
    private void forceRepaintInThread(CountingLessonView view) {
        final CountingLessonView view2 = view;
        Thread myRepaintThread = new Thread() {
            public void run() {
                view2.repaintCountingPanel();
            }
        };
        // Important: Swing is not thread safe, must always use
        // SwingUtilities if not the event dispatch thread.
        SwingUtilities.invokeLater(myRepaintThread);
    }
        
    public void numberButtonPressed(int buttonIndex, CountingLessonView view) {
        view.setBusy(true);
        playAudioForNumber(currentStartingNumber + buttonIndex, view);
    }
        
    private void playAudioForNumber(int number, CountingLessonView view) {
        AudioPlayer audioPlayer = new AudioPlayer();
        byte[] audioData = getAudioSampledData(number); 
        audioPlayer.playAudio(audioData);
        try {
            Thread.sleep(100);
        }
        catch (InterruptedException ie) {
            System.out.println("Thread interrupted");
        }
        view.setBusy(false);
    }
        
    public void backButtonPressed(CountingLessonView view) {
        if (currentStartingNumber == minStartingNumber) 
            return;
        currentStartingNumber -= standardIncrementValue;
        view.initializeCountingButtons();
        view.showCountingButtons();
    }
        
    public void forwardButtonPressed(CountingLessonView view) {
        if (currentStartingNumber == maxStartingNumber) {
            // Lesson is over
           	lessonEnd(true);
            return;
        }
        currentStartingNumber += standardIncrementValue;
        view.initializeCountingButtons();
        view.showCountingButtons();
    }
        
    public ImageIcon getImageIcon(int numberToShow) {
        String resourceImageId = null;
               
        resourceImageId = ChildrenResource.NUMBER_IMAGE_MAP.get(numberToShow);
              
        // Get the numberIcon from the resource to display 
        ImageIcon numberImageIcon = null;
        numberImageIcon = provider.getScaledImage(resourceImageId, 0.7f);
              
        return numberImageIcon;
    }
        
    public byte[] getAudioSampledData(int numberToPlay) {
        byte[] audioData = null;
                
        audioData = provider.getAudioContentByNumber(numberToPlay);
        return audioData;
    }
        
    public void lessonStart() {
      	currentStartingNumber = 1;
        	
      	for (Lesson l : LessonGameManager.getAllLessons()) {
   		    if (l.getName().contains("Count"))
   			    start(l);
      	}
    }
        
    public void lessonEnd(boolean complete) {
       	if (isActive())
       		stop(complete);
        	
       	if (complete) {
       		getMainFrame().getController(LessonResultsController.class)
       			.showResultScreen(getEarnedAchievements());
       	}
    }
}